Buffers are used to coordinate the data streams of two devices operating at different speeds. Conventional first-in first-out (FIFO) buffers (or circular buffers) may employ status flags to indicate when particular boundary conditions (such as full, empty, almost full, almost empty, overflow, underflow, etc.) are present. When a particular boundary condition is present, the status flags may disable the reading and/or writing of information to or from the buffer. However, in applications where it is not convenient to simply stop reading and/or writing to the buffer, such as in an Ethernet repeater where the buffer is in the data stream, certain design constraints may change such as the ability to retrieve information from a different layer of the Ethernet protocol and/or the inability to simply stop the input or output data stream.
It is generally necessary to detect overflow and underflow conditions in a circular buffer. Conventional solutions to detecting overrun and underrun conditions employ some type of counting scheme. A counter may be updated dynamically as data is written to or read from the buffer. For example, a counter may keep track of the number of unoccupied locations in the data buffer. If the number of occupied locations falls to a predetermined value approaching zero, a signal indicating that the data buffer is "almost empty" is presented. If the number of occupied locations becomes large, reaching a predetermined value close to the storage capacity of the data buffer, a signal indicating a buffer is "almost full" is presented. Using such conventional counting methods, logic must be implemented to keep track of the up/down counting function. The design must manage the complexities of a single counter controlled and clocked simultaneously from two clock domains. As a result, such conventional counters grow in proportion to the number of address locations in the data buffer.